﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using DevExpress.XtraBars.Docking2010.Views.WindowsUI;
using EduFormManager.Models;
using EduFormManager.Models.Repo;
using EduFormManager.Properties;
using ItemCheckEventArgs = DevExpress.XtraEditors.Controls.ItemCheckEventArgs;

namespace EduFormManager.Forms.UserControls
{
    public partial class XtraDictionaryFormsControl : XtraBaseControl, ISupportDocumentActions
    {
        private bool m_isManualChecking;
        private Allform m_selectedForm;
        public XtraDictionaryFormsControl(WindowsUIView view)
            : base(view)
        {
            InitializeComponent();
            InitializeProps();

            m_isManualChecking = true;
        }

        private void InitializeProps()
        {
            this.allformBindingSource.DataSourceChanged += (s, e) => 
            {
                IList<Allform> formList = this.allformBindingSource.List as List<Allform>;
                RebuildAllformTree(formList);
                SelectFormNode(m_selectedForm);
            };
            this.allformBindingSource.ListChanged += (s, e) => 
            {
                if (e.ListChangedType == ListChangedType.ItemAdded ||
                    e.ListChangedType == ListChangedType.ItemChanged)
                {
                    Allform form = this.allformBindingSource.List[e.NewIndex] as Allform;
                    if (!_editedList.Contains(form))
                        _editedList.Add(form);
                }

                IList<Allform> formList = this.allformBindingSource.List as List<Allform>;
                RebuildAllformTree(formList);
                SelectFormNode(m_selectedForm);
            };

            //this.comboBoxAllformType.SelectedIndexChanged += (s, e) => 
            //{
            //    AllformType type = this.comboBoxAllformType.SelectedItem as AllformType;
            //    if (type == null)
            //        return;
            //    if (type.Id == (int)AllformType.Type.Types.Municipality)
            //    {
            //        this.checkedListBoxEduKinds.Enabled = false;
            //        UncheckAllEdukindList();
            //    }
            //    else
            //    {
            //        this.checkedListBoxEduKinds.Enabled = true;
            //    }
            //};
        }

        private void RebuildAllformTree(IList<Allform> formList)
        {
            this.treeViewForms.Nodes.Clear();
            TreeNode[] nodeList = GetFormNodelist(formList);
            this.treeViewForms.Nodes.AddRange(nodeList);
            this.treeViewForms.ExpandAll();
        }

        private void SelectFormNode(Allform form)
        {
            if (form != null)
            {
                TreeNode[] foundNodes = this.treeViewForms.Nodes.Find(form.Name, true);
                if (foundNodes.Length > 0)
                {
                    this.treeViewForms.SelectedNode = foundNodes[0];
                }
            }
        }

        private TreeNode[] GetFormNodelist(IList<Allform> formList)
        {
            List<TreeNode> nodeList = new List<TreeNode>();
            var groupList = formList.GroupBy(x => x.Type);
            foreach (var groupItem in groupList)
            {
                if (groupItem.Key == null)
                    continue;
                TreeNode typeNode = new TreeNode() 
                { 
                    Text = groupItem.Key.TypeName, 
                    Name =  groupItem.Key.TypeName,
                    Tag = groupItem.Key
                };
                foreach (var item in groupItem)
                {
                    TreeNode formNode = new TreeNode() 
                    {
                        Text = _editedList.Contains(item) ? item.Name + "*" : item.Name,
                        Name = item.Name,
                        Tag = item
                    };
                    typeNode.Nodes.Add(formNode);
                }
                nodeList.Add(typeNode);
            }
            return nodeList.ToArray();
        }

        private void UncheckAllEdukindList()
        {
            m_isManualChecking = false;
            this.checkedListBoxEduKinds.UnCheckAll();
            m_isManualChecking = true;
        }

        private void CheckEdukindList(IEnumerable<EduOrgKind> list)
        {
            m_isManualChecking = false;
            if (list != null)
            {
                foreach (EduOrgKind kind in list)
                {
                    int idx = this.checkedListBoxEduKinds.FindItem(kind);
                    if (idx >= 0 && idx < this.checkedListBoxEduKinds.ItemCount)
                        this.checkedListBoxEduKinds.SetItemChecked(idx, true);
                }
            }
            m_isManualChecking = true;
        }

        private void SelectAllformType(AllformType type)
        {
            m_isManualChecking = false;
            this.comboBoxAllformType.SelectedItem = type;
            m_isManualChecking = true;
        }

        private void treeViewForms_AfterSelect(object sender, TreeViewEventArgs e)
        {
            UncheckAllEdukindList();
            layoutControlGroup2.Enabled = true;
            if (e.Node.Tag is Allform)
            {
                Allform form = e.Node.Tag as Allform;
                m_selectedForm = form;
                int idxForm = this.allformBindingSource.List.IndexOf(form);
                this.allformBindingSource.Position = idxForm;
                CheckEdukindList(form.EduOrgKinds);
                SelectAllformType(form.Type);
            }
            else
            {
                layoutControlGroup2.Enabled = false;
            }
        }

        private void comboBoxAllformType_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (m_isManualChecking)
            {
                AllformType type = this.comboBoxAllformType.SelectedItem as AllformType;
                Allform form = this.allformBindingSource.Current as Allform;
                if (type != form.Type)
                {
                    form.Type = type;
                    if (!_editedList.Contains(form))
                        _editedList.Add(form);
                    IList<Allform> formList = this.allformBindingSource.List as List<Allform>;
                    RebuildAllformTree(formList);
                }
            }
        }

        private void checkedListBoxEduKinds_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            if (m_isManualChecking)
            {
                EduOrgKind kind = this.checkedListBoxEduKinds.GetItem(e.Index) as EduOrgKind;
                Allform form = this.allformBindingSource.Current as Allform;
                if (e.State == CheckState.Checked)
                {
                    form.EduOrgKinds.Add(kind);
                }
                else
                {
                    form.EduOrgKinds.Remove(kind);
                }
                if (!_editedList.Contains(form))
                    _editedList.Add(form);
            }
        }

        async protected override void Remove(Document doc)
        {
            if (!CanRemove(doc))
            {
                this.ShowFlyoutMessageBox("Информация", "Не выбран элемент для удаления", FlyoutCommand.OK);
                return;
            }
            
            Allform form = this.allformBindingSource.Current as Allform;
            ProgressDialog.ShowTop(this.ParentForm, description: "Обработка");
            StringBuilder messageBuilder = new StringBuilder(String.Format("Удалить Форму {0}?", form));
            await Task.Run(() => 
            {
                IList<FormData> formDataList = RepoHelper.Repo.GetEduFormData(form);
                if (formDataList.Count > 0)
                {
                    messageBuilder.AppendLine("\nВместе с формой будут удалены загруженные файлы");
                    messageBuilder.AppendLine(string.Join<FormData>("; ", formDataList));
                }
                if (form.FormQueries.Count > 0)
                {
                    messageBuilder.AppendLine("\nВместе с формой будут удалены запросы");
                    messageBuilder.AppendLine(string.Join<Query>(";", form.FormQueries));
                }
            });
            ProgressDialog.HideTop();
            
            DialogResult dialogResult = this.ShowFlyoutMessageBox("Подтверждение", messageBuilder.ToString(), FlyoutCommand.Yes, FlyoutCommand.No);
            if (dialogResult == DialogResult.Yes)
            {
                try
                {
                    RepoHelper.Repo.Delete(form);
                    this.allformBindingSource.Remove(form);
                    this.allformBindingSource.EndEdit();
                }
                catch (Exception ex)
                {
                    this.ShowFlyoutMessageBox("Ошибка", ex.Message, FlyoutCommand.OK);
                }
                
            }
        }

        protected override bool CanRemove(Document doc)
        {
            return (this.allformBindingSource.Current as Allform) != null;
        }

        protected override bool CanSave(Document doc)
        {
            return true;
        }

        async protected override void Save(Document doc)
        {
            if (!CanSave(doc))
            {
                this.ShowFlyoutMessageBox("Ошибка", "Проверьте заполнены ли все поля.", FlyoutCommand.OK);
            }
            ProgressDialog.ShowTop(this.ParentForm, description: "Сохраняю");
            await Task.Run(() => 
            {
                //this.allformBindingSource.EndEdit();
                List<Allform> allformLeftList = new List<Allform>();
                foreach (Allform form in _editedList)
                {
                    if (!string.IsNullOrEmpty(form.Name) && form.ExpireDate != null && form.Type != null)
                        RepoHelper.Repo.Save(form);
                    else
                        allformLeftList.Add(form);
                }
                _editedList.Clear();
                _editedList.AddRange(allformLeftList);
            });
            this.RebuildAllformTree(this.allformBindingSource.List as List<Allform>);
            ProgressDialog.HideTop();
            if (_editedList.Count != 0)
            {
                this.ShowFlyoutMessageBox("Информация", "Несохраненные объекты помечены символом '*'", FlyoutCommand.OK);
            }
        }

        protected override bool CanNew(Document doc)
        {
            return true;
        }

        protected override void New(Document doc)
        {
            UncheckAllEdukindList();
            
            this.textBoxName.Text = "Новая форма";
            this.dateEditExpire.Value = DateTime.Now;
            Allform form = new Allform();
            form.Type = this.comboBoxAllformType.SelectedItem as AllformType;
            form.Name = this.textBoxName.Text;
            this.allformBindingSource.Add(form);
            m_selectedForm = form;
            this.allformBindingSource.Position = this.allformBindingSource.List.IndexOf(form);
            IList<Allform> formList = this.allformBindingSource.List as List<Allform>;
            RebuildAllformTree(formList);
        }

        public void OnQueryDocumentActions(IDocumentActionsArgs args)
        {
            args.DocumentActions.Add(new DocumentAction(New) { Caption = "Новая форма", Image = Resources.glyphicons_432_plus });
            args.DocumentActions.Add(new DocumentAction(Save) { Caption = "Сохранить", Image = Resources.glyphicons_206_ok_2 });
            args.DocumentActions.Add(new DocumentAction(Remove) { Caption = "Удалить", Image = Resources.glyphicons_207_remove_2 });
        }

        private void textBoxName_Validating(object sender, CancelEventArgs e)
        {
            foreach (Allform form in this.allformBindingSource.List)
            {
                if (form != m_selectedForm && form.Name == this.textBoxName.Text)
                {
                    this.ShowFlyoutMessageBox("Информация", String.Format("Форма с таким именем уже существует:\n{0}, {1}", form.Type, form.Name), FlyoutCommand.OK);
                    e.Cancel = true;
                    return;
                }
            }
            e.Cancel = false;
        }

       


    }
}
